package com.zengchen.content.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zengchen.common.bean.ResponseVO;
import com.zengchen.common.enums.ResponseCode;
import com.zengchen.content.auth.CheckLogin;
import com.zengchen.content.common.PoemOT;
import com.zengchen.content.entity.Poem;
import com.zengchen.content.feignclient.UserCenterFeignClient;
import com.zengchen.content.service.PoemService;
import com.zengchen.user.common.CurrentPoemOT;
import com.zengchen.user.common.ReciteHisOT;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author zengchen123
 * @since 2019-08-03
 */
@RestController
@RequestMapping("poem")
public class PoemController {

    private static final Logger log = LoggerFactory.getLogger(PoemController.class);

    @Autowired
    private PoemService poemService;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private UserCenterFeignClient userCenterFeignClient;

    private static final String RECITE_SUCCESS = "good";

    private static final String RECITE_FAIL = "wrong";

    @GetMapping(value = "testRibbon")
    @CheckLogin
    public Object testRibbon() {
        //1. 未使用Ribbon时
//        List<ServiceInstance> instances = discoveryClient.getInstances("user-center");
//        String targetUrl = instances.stream()
//                .map(instance -> instance.getUri().toString() + "/reciteHis/testAno")
//                .findFirst()
//                .orElseThrow(() -> new IllegalArgumentException("当前没有实例！"));

        // 2.Ribbon + restTemplate
//        String targetUrl= "http://user-center/reciteHis/testAno";
//        Page page = restTemplate.getForObject(targetUrl, Page.class);

        // 3.Feign
        Page<ReciteHisOT> page = userCenterFeignClient.memberRctHisAno();
        return ResponseVO.success(page);
    }

    /**
     * 获取所有诗词
     *
     * @return
     */
    @GetMapping(value = "getAllPoem")
    public List<PoemOT> getAllPoem() {
        log.info("getAllPoem start ......");
        List<Poem> list = poemService.list();
        List<PoemOT> poemOTs = list.stream().map(e -> {
            PoemOT poemOT = new PoemOT();
            BeanUtils.copyProperties(e, poemOT);
            return poemOT;
        }).collect(Collectors.toList());
        log.info("getAllPoem end size = {} ......",poemOTs.size());
        return poemOTs;
    }

    /**
     * 根据这一首诗词的id 找到排序在它后面的第一首诗的 id
     *
     * @param id
     * @return
     */
    @GetMapping(value = "getNextPoemId")
    public Integer getNextPoemId(Integer id) {
        log.info("getNextPoemId id={} start ......");
        Poem poem = Optional.ofNullable(poemService.getById(id)).orElseThrow(() -> new IllegalArgumentException("找不到 id=" + id + " 的诗词"));
        Integer order = poem.getOrders();
        PoemOT poemOT = getPoemByOrder(order + 1);
        // TODO 当诗没了的时候，应该返回的诗词id
        Integer returnId = 1;
        if(null != poemOT){
            returnId = poemOT.getId();
        }
        log.info("getNextPoemId end id = {} ......",returnId);
        return returnId;
    }

    @GetMapping(value = "{id}")
    public PoemOT getPoem(@PathVariable Integer id) {
        Poem poem = poemService.getById(id);
        PoemOT poemOT = new PoemOT();
        BeanUtils.copyProperties(poem, poemOT);
        return poemOT;
    }

    @GetMapping("getPoemByOrder")
    public PoemOT getPoemByOrder(Integer order) {
        log.info("getPoemByOrder start with order={}", order);
        List<Poem> list = poemService.list(new QueryWrapper<Poem>()
                .ge("orders", order)
                .orderByAsc("orders")
        );
        if (CollectionUtils.isEmpty(list)) {
            log.warn("getPoemByOrder success end with no right record");
            return null;
        }
        PoemOT poemOT = new PoemOT();
        BeanUtils.copyProperties(list.get(0), poemOT);
        log.info("getPoemByOrder success end with poemId={}", poemOT.getId());
        return poemOT;
    }

    @GetMapping(value = "list")
    public Object listByIds(String ids) {
        ResponseVO responseVO = new ResponseVO();
        log.info("listByIds start with ids:{}", ids);
        try {
            if (StringUtils.isBlank(ids)) {
                log.info("listByIds 参数ids为空！");
                responseVO.setCode(1);
                responseVO.setMsg("参数ids为空！");
                return responseVO;
            }
            List<String> idList = Arrays.asList(ids.split(","));
            Collection<Poem> poems = poemService.listByIds(idList);
            responseVO.setData(poems);
        } catch (Exception e) {
            log.error("查询异常", e);
            responseVO.setCode(2);
            responseVO.setMsg("服务内部发生异常");
            return responseVO;
        }
        responseVO.setCode(0);
        responseVO.setMsg("Ok");
        return responseVO;
    }

    @GetMapping(value = "checkRecite")
    @CheckLogin
    public Object checkRecite(Integer poemId, String reciteContent, HttpServletRequest request) {
        Map<String, Object> responseData = new HashMap<>();
        Integer memberId = (Integer) request.getAttribute("memberId");
        log.info("checkRecite start with poemId={},memberId={},reciteContent={}", poemId, memberId, reciteContent);

        // 1.检查参数是否合规
        if (StringUtils.isBlank(reciteContent) || poemId == null) {
            log.info("checkRecite end with poemId is null or reciteContent is blank！");
            return ResponseVO.fail(ResponseCode.ERROR_PARAMS);
        }
        Poem poem = Optional.ofNullable(poemService.getById(poemId)).orElseThrow(() -> new IllegalArgumentException("not found poem"));
        // 2.检查是否已经背诵过，token已经在拦截器里带到请求的header里去了，所以这里只用传一个poemId
        ReciteHisOT reciteHisOT = userCenterFeignClient.getReciteHis(poemId);
        if (reciteHisOT != null && reciteHisOT.getPoemId() != null) {
            return ResponseVO.fail(ResponseCode.ERROR_ALREADY_RECITE);
        }
        // 3.对比提交内容，得出背诵结果
        log.info("onlyContent={}", poem.getOnlyContent());
        String reciteResult = reciteContent.equals(poem.getOnlyContent()) ? RECITE_SUCCESS : RECITE_FAIL;
        responseData.put("reciteResult", reciteResult);

        // 4.如果背诵成功，入库 ReciteHis 表，更新currentPoem表状态
        // TODO 使用消息队列 做成异步的
        if (RECITE_SUCCESS.equals(reciteResult)) {
            PoemOT poemOT = new PoemOT();
            BeanUtils.copyProperties(poem, poemOT, "createTime", "updateTime","mp3",
                    "appreciation1","appreciation2","appreciation3","only_content","content");
            userCenterFeignClient.insertReciteHis(poemOT);

            CurrentPoemOT currentPoemOT = new CurrentPoemOT();
            currentPoemOT.setMemberId(memberId);
            currentPoemOT.setPoemId(poemId);
            currentPoemOT.setStatus("Y");
            userCenterFeignClient.updateCurrentPoem(currentPoemOT);
        }

        log.info("checkRecite end with reciteResult={}", reciteResult);
        return ResponseVO.success(responseData);
    }

    public static void main(String[] args) {
        System.out.println(ThreadLocalRandom.current().nextInt(1,2));
        System.out.println(ThreadLocalRandom.current().nextInt(1,2));
        System.out.println(ThreadLocalRandom.current().nextInt(1,2));
        System.out.println(ThreadLocalRandom.current().nextInt(1,2));
        System.out.println(ThreadLocalRandom.current().nextInt(1,2));
    }

}

